package com.gtenacg.fileservice.util;

import com.gtenacg.fileservice.compent.FileTypeProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

@Slf4j
@Component
@RequiredArgsConstructor
public class FileUtil {
    final FileTypeProperties fileTypeProperties;

    public String getFileExtension(String filePath) {
        Path path = Paths.get(filePath);
        String fileName = path.getFileName().toString();
        int dotIndex = fileName.lastIndexOf('.');
        if (dotIndex == -1) {
            // 没有后缀名
            return "";
        }
        return fileName.substring(dotIndex + 1);
    }

    public String getContentType(String fileExtension) {
        if (fileTypeProperties.getImage().getSupportedFormats().contains(fileExtension)) {
            return "image/" + fileExtension;
        }
        else if (fileTypeProperties.getText().getSupportedFormats().contains(fileExtension)) {
            if (fileExtension.equals("txt")) return "text/plain";
            return "text/" + fileExtension;
        }
        else if (fileTypeProperties.getApplication().getSupportedFormats().contains(fileExtension)) {
            return "application/" + fileExtension;
        }
        else {
            return "application/octet-stream";
        }
    }

    public boolean deleteDirectory(File directory) {

        if (directory.exists()) {
            File[] entries = directory.listFiles();

            if (entries != null) {
                for (File entry : entries) {

                    if (entry.isDirectory()) {
                        deleteDirectory(entry); // 递归删除子目录
                    } else {
                        boolean delete = entry.delete();// 删除文件
                        if (!delete) {
                            log.warn("删除文件失败：" + entry.getAbsolutePath());
                        }
                    }

                }
            }

        }

        // 删除目录本身
        return directory.delete();
    }

    // 将文件夹压缩成zip，并直接输出到指定流
    public void zipFolder(File folder, OutputStream out) throws IOException {
        File[] files = folder.listFiles();
        if (files == null) return;
        byte[] buffer = new byte[1024 * 1024 * 5];

        ZipOutputStream zos = new ZipOutputStream(out);

        // 添加文件夹到zip
        String prefix = folder.getName() + "/";
        zos.putNextEntry(new ZipEntry(prefix));
        zos.closeEntry();

        // 遍历文件夹中的文件和子文件夹
        for (File file : files) {
            if (file.isDirectory()) {
                zipFolder(file, zos); // 递归处理子文件夹
            } else {
                // 添加到zip
                FileInputStream fis = new FileInputStream(file);
                ZipEntry zipEntry = new ZipEntry(prefix + file.getName());
                zos.putNextEntry(zipEntry);

                int len;
                while ((len = fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, len);
                }

                zos.closeEntry();
                fis.close();
            }
        }

        zos.close();
    }

    // 压缩文件或文件夹
    public void toZip(File src) throws IOException {
        //创建压缩包
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(
                new File(src.getParentFile(), src.getName() + "-zip.zip")
        ));
        if (src.isFile()) {
            ZipEntry Entry = new ZipEntry(src.getName());
            zos.putNextEntry(Entry);
            FileInputStream fis = new FileInputStream(src);
            BufferedInputStream bis = new BufferedInputStream(fis);
            byte[] buffer = new byte[1024 * 1024 * 5];
//            int b;
//            while((b = fis.read()) != -1) {
//                zos.write(b);
//            }
            while(bis.read(buffer) != -1) {
                zos.write(buffer);
            }
            fis.close();
            zos.close();

        } else {
            //拷贝并压缩文件
            putEntry(src, zos, src.getName());
            zos.close();
        }



    }

    // 递归压缩文件夹，并写入zip流
    private void putEntry(File src, ZipOutputStream zos, String dirName) throws IOException {
        //遍历文件夹
        for (File file : Objects.requireNonNull(src.listFiles())) {
            if (file.isFile()) {
                //拷贝文件
                ZipEntry Entry = new ZipEntry(dirName + "\\" + file.getName());
                zos.putNextEntry(Entry);

                FileInputStream fis = new FileInputStream(file);
                BufferedInputStream bis = new BufferedInputStream(fis);
                byte[] buffer = new byte[1024 * 1024 * 5];

                while(bis.read(buffer) != -1) {
                    zos.write(buffer);
                }
                fis.close();
                zos.closeEntry();
            }
            if (file.isDirectory()) {
                //dirName: 需要传递压缩包内所有层级的文件夹
                putEntry(file, zos, dirName + "\\" + file.getName());
            }
        }
    }

    // 解压zip
    public void unzip(File src, File target) throws IOException {
        ZipInputStream zip = new ZipInputStream(new FileInputStream(src));

        ZipEntry entry;
        while((entry = zip.getNextEntry()) != null) {
            System.out.println(entry);
            if (entry.isDirectory()) {
                new File(target, entry.getName()).mkdirs();
            } else {
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(target, entry.getName())));
                int len;
                byte[] bytes = new byte[1024 * 1024];
                while((len = zip.read(bytes)) != -1) {
                    bos.write(bytes, 0, len);
                }
                bos.close();
                zip.closeEntry();
            }
        }
        zip.close();
    }
}
